
#include <unistd.h>
#include <cstdio>

#include "httputil.h"

const string HTTPUtil::methodString(HTTPMethod method)
{
    if (method == MethodGET)
        return "GET";
    else if (method == MethodPOST)
        return "POST";
    else if (method == MethodHEAD)
        return "HEAD";
    else
        return "ERROR";
}

bool HTTPUtil::readline(string& str, bool *eof, int fd) {
    str.clear();
    ssize_t nread;
    char read_char;
    *eof = false;
    while ((nread = read(fd, &read_char, 1)) != -1) {
        if (nread == 0) {
            *eof = true;
            return true;
        }
        if (read_char != '\n')
            str.append(1, read_char);
        else
            return true;
    }
    perror("readline");
    return false;
}

bool HTTPUtil::parseRequestLine(HTTPMethod& method, string& path, string& version, const string& str) {
    size_t firstSpacePos = str.find(' ');
    if (firstSpacePos == string::npos)
        return false;
    const string methodStr(str, 0, firstSpacePos);
    if (methodStr == "GET")
        method = MethodGET;
    else if (methodStr == "POST")
        method = MethodPOST;
    else if (methodStr == "HEAD")
        method = MethodHEAD;
    else
        method == nMethod;
    size_t secSpacePos = str.find(' ', firstSpacePos+1);
    if (secSpacePos == string::npos)
        return false;
    path = str.substr(firstSpacePos+1, secSpacePos - firstSpacePos - 1);
    version = str.substr(secSpacePos+1);
    return true;
}

bool HTTPUtil::readBytes(string& buffer, int fd, int length) {
    char buf[256];ssize_t nread, nask;
    while (length) {
        nask = length < 256 ? length : 256;
        nread = read(fd, buf, nask);
        if (nread == -1) {
            perror("readBytes");
            return false;
        }
        if (nread == 0)
            break;
        length -= nread;
        buffer.append(buf, nread);
    }
    return true;
}

bool HTTPUtil::writeBytes(const char* buffer, int fd, int length) {
    ssize_t nwrite, nask;
    while (length) {
        nask = length < 256 ? length : 256;
        nwrite = write(fd, buffer, nask);
        if (nwrite == -1) {
            perror("writeBytes");
            return false;
        }
        if (nwrite == 0)
            break;
        length -= nwrite;
        buffer += nwrite;
    }
    return true;
}

bool HTTPUtil::copy(int infd, int outfd, int length)
{
    ssize_t nread, nask;char buf[256];
    while (length) {
        nask = length < 256 ? length : 256;
        nread = read(infd, buf, nask);
        if (nread == -1) {
            perror("readBytes");
            return false;
        }
        if (nread == 0)
            break;
        if (!writeBytes(buf, outfd, nread))
            return false;
        length -= nread;
    }
    return true;
}
